package no.rodland.acc.parsers;

import org.constretto.annotation.Configuration;
import org.constretto.annotation.Configure;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.IllegalFieldValueException;
import org.joda.time.MutableDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 *
 * @Since: Jun 21, 2010 10:59:49 AM
 * @Author: fmr
 */
public class TextDateParser {
    private DateTimeFormatter fmt;
    private Pattern p;
    private int secsNearDate;

    @Configure
    public void configure(
            @Configuration(expression = "import.days_near_date")
            int daysNearDate,
            @Configuration(expression = "import.date_format_from_text")
            String dateFormatFromText,
            @Configuration(expression = "import.regexp_date_from_text")
            String regexpDateFromText) {
        this.secsNearDate = 60 * 60 * 24 * daysNearDate;
        fmt = DateTimeFormat.forPattern(dateFormatFromText);
        p = Pattern.compile(regexpDateFromText);
    }

    public DateTime parse(String string, DateTime nearDate) {
        String subString = getSubString(string);
        if (subString == null) {
            return null;
        }

        DateTime dt2 = null;
        try {
            DateTime dt = fmt.parseDateTime(subString);
            dt2 = setYear(dt, nearDate);
        }
        catch (IllegalFieldValueException ifv) {
            // okidok, will just return null
        }
        return dt2;
    }

    private DateTime setYear(DateTime proposal, DateTime nearDate) {
        MutableDateTime d = proposal.toMutableDateTime();
        if (nearDate == null) {
            nearDate = new DateTime();
        }
        int year = nearDate.getYear();
        int month = nearDate.getMonthOfYear();
        d.setYear(year);

        Duration duration = new Duration(d, nearDate);
        long seconds = Math.abs(duration.getStandardSeconds());
        if (seconds > secsNearDate) {
            if (month == 12) {
                d.setYear(year + 1);
                duration = new Duration(d, nearDate);
                long seconds2 = Math.abs(duration.getStandardSeconds());
                if (seconds2 < seconds) {
                    return new DateTime(d);
                }
                d.setYear(year);
            }
            else if (month == 1) {
                d.setYear(year - 1);
                duration = new Duration(d, nearDate);
                long seconds2 = Math.abs(duration.getStandardSeconds());
                if (seconds2 < seconds) {
                    return new DateTime(d);
                }
                d.setYear(year);
            }
        }
        return new DateTime(d);
    }

    private String getSubString(String string) {
        if (string == null || string.length() < 5) {
            return null;
        }

        Matcher m = p.matcher(string);
        if (m.matches()) {
            return m.group(1);
        }
        return null;
    }
}